package com.zmn.plat.business.impl.product;

import com.google.common.base.Joiner;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.plat.business.interfaces.product.ServProductRelationBService;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.product.ServProductQuery;
import com.zmn.plat.model.entity.product.ServProductRelation;
import com.zmn.plat.model.entity.product.ServProductRelationQuery;
import com.zmn.plat.model.vo.product.relation.ServProductRelationOperatorVO;
import com.zmn.plat.model.vo.product.relation.ServProductRelationVO;
import com.zmn.plat.services.interfaces.product.ServProductRelationService;
import com.zmn.plat.services.interfaces.product.ServProductService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tanbiao
 * @description
 * @modifier
 * @since 2019/11/27 17:02
 **/
@Service
public class ServProductRelationBServiceImpl implements ServProductRelationBService {

    @Resource
    private ServProductRelationService servProductRelationService;
    @Resource
    private ServProductService servProductService;

    @Override
    public Integer deleteBatch(List<Integer> ids, Integer showProductId) {
        ServProduct product = servProductService.findByKey(showProductId);
        if (Objects.isNull(product)) {
            throw new PlatException("前台产品不存在，请检查操作是否合法");
        }
        // 不检查下架的产品
        if (Objects.equals(product.getStatus(), GlobalConsts.YES)) {
            // 删除关联关系必须至少保留一个上架的后台产品
            ServProductRelationQuery query = new ServProductRelationQuery();
            query.setShowProductId(showProductId);
            // 关联的所有后台产品
            List<ServProductRelationVO> list = servProductRelationService.listByQueryForShow(query);
            List<ServProductRelationVO> unDeleteVo = new ArrayList<>();
            for (ServProductRelationVO vo : list) {
                if (!ids.contains(vo.getId())) {
                    unDeleteVo.add(vo);
                }
            }
            unDeleteVo = unDeleteVo.stream().filter(e -> e.getStatus().equals(GlobalConsts.YES)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(unDeleteVo)) {
                throw new PlatException("前台产品必须关联至少一个上架的后台产品；并且不能间接关联多个后台一级产品");
            }
        }

        return servProductRelationService.deleteBatch(ids);
    }

    /**
     * 功能描述 ：一个后台产品对应一个前台产品，一个计价器产品对应多个后台产品，但是不存在多个计价器产品关联一个后台产品的情况 关联关系的新增取消，需要检查其他前台产品是否关联该后台产品，如果是需要给他保留至少一个上架的后台产品才能执行绑定关系的修改
     *
     * @param vo
     * @return java.lang.Integer
     * @author tanbiao
     * @modifier
     * @since 2019/9/24
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateRelations(ServProductRelationOperatorVO vo) {
        // 查询后台产品已关联的数据
        List<Integer> productIds = vo.getProductIds();
        List<Integer> exitsProductIds = new ArrayList<>();
        // 后台产品id查询所有的和该后台产品已经有关联关系的前台产品对应的所有后台产品
        List<ServProductRelationVO> relations = servProductRelationService.listByProductIds(productIds);
        // 前台渠道产品在关联后台产品时,选择的后台产品（通用&渠道）是否已经关联过前台产后，已经关联的不能再关联（只判断有效的）
        checkEffectiveProduct(relations, productIds);
        List<ServProductRelation> insertRelations = new ArrayList<>();
        // 选择的后台产品没有关联任何计价器产品，此时不做检查直接插入关联关系即可
        if (CollectionUtils.isEmpty(relations)) {
            for (Integer productId : vo.getProductIds()) {
                insertRelations.add(getNewRelation(vo.getOperator(), productId, vo.getShowProductId()));
            }
        } else {
            for (ServProductRelationVO relation : relations) {
                // 已存在关联关系，需要检查关系修改之后，会不会造成之前有关联关系的计价器产品存在没有启用状态的后台产品
                if (productIds.contains(relation.getProductId())) {
                    exitsProductIds.add(relation.getProductId());
                    if (!Objects.equals(relation.getShowProductId(), vo.getShowProductId())) {
                        relation.setStatus(GlobalConsts.NO);
                    }
                }
            }
            // 变更关系之后是否存在将原有的计价器不存在上架的后台产品了
            List<Integer> disableTariffProductIds = new ArrayList<>();
            Map<Integer, List<ServProductRelationVO>> tariffIdProductRelationMap = relations.stream().collect(Collectors.groupingBy(ServProductRelationVO::getShowProductId));
            tariffIdProductRelationMap.forEach((k, v) -> {
                if (!CollectionUtils.isEmpty(v)) {
                    // 下架状态的计价器产品不做状态控制
                    Integer showStatus = v.get(0).getShowStatus();
                    if (Objects.equals(showStatus, GlobalConsts.YES)) {
                        List<ServProductRelationVO> enableList = v.stream().filter(e -> Objects.equals(e.getStatus(), GlobalConsts.YES)).collect(Collectors.toList());
                        if (CollectionUtils.isEmpty(enableList)) {
                            disableTariffProductIds.add(k);
                        }
                    }
                }
            });
            if (!CollectionUtils.isEmpty(disableTariffProductIds)) {
                List<ServProduct> products = servProductService.listByIdList(disableTariffProductIds);
                StringBuilder message = new StringBuilder();
                products.forEach(e -> {
                    if (Objects.equals(e.getStatus(), GlobalConsts.YES)) {
                        message.append(e.getName()).append("、");
                    }
                });
                if (message.length() > 0) {
                    message.deleteCharAt(message.length() - 1).toString();
                    String error = new StringBuilder("该后台产品已关联前台产品：【").append(message).append("】,请先取消关联后再操作！").toString();
                    throw new PlatException(error);
                }
            }

            for (Integer productId : productIds) {
                if (!exitsProductIds.contains(productId)) {
                    insertRelations.add(getNewRelation(vo.getOperator(), productId, vo.getShowProductId()));
                }
            }
        }
        if (!CollectionUtils.isEmpty(insertRelations)) {
            servProductRelationService.insertBatch(insertRelations);
        }
        if (!CollectionUtils.isEmpty(exitsProductIds)) {
            ServProductRelation relation = new ServProductRelation();
            relation.setShowProductId(vo.getShowProductId());
            relation.setUpdater(vo.getOperator());
            relation.setUpdateTime(new Date());
            servProductRelationService.updateBatch(relation, exitsProductIds);
        }
        return productIds.size();
    }

    private ServProductRelation getNewRelation(String operator, Integer productId, Integer showProductId) {
        ServProductRelation insertRelation = new ServProductRelation();
        insertRelation.setCreater(operator);
        insertRelation.setCreateTime(new Date());
        insertRelation.setProductId(productId);
        insertRelation.setShowProductId(showProductId);
        insertRelation.setStatus(GlobalConsts.YES);
        return insertRelation;
    }

    private void checkEffectiveProduct(List<ServProductRelationVO> relations, List<Integer> sourceProductIds) {
        List<ServProductRelationVO> errerlist = relations.stream()
                .filter(e -> Objects.equals(e.getStatus(), GlobalConsts.YES))
                .collect(Collectors.toList());
        if (CollectionUtil.isNotNullOrEmpty(errerlist)) {
            //前端产品id
            List<Integer> showProductId = errerlist.stream()
                    .map(ServProductRelationVO::getShowProductId)
                    .distinct()
                    .collect(Collectors.toList());
            //后端产品id
            List<Integer> productId = errerlist.stream()
                    .map(ServProductRelationVO::getProductId)
                    .distinct()
                    .collect(Collectors.toList());
            // 获取前后端有效产品
            productId.addAll(showProductId);
            ServProductQuery query = new ServProductQuery();
            query.setProductIds(productId);
            query.setStatus(GlobalConsts.YES);
            List<ServProduct> products = servProductService.listByQuery(query);
            // 已关联有效的前台产品
            List<String> showProductName = products.stream()
                    .filter(e -> Objects.equals(e.getShowType(), GlobalConsts.YES))
                    .map(ServProduct::getName).collect(Collectors.toList());
            // 已关联有效的后台产品
            List<String> productName = products.stream()
                    .filter(e -> Objects.equals(e.getShowType(), GlobalConsts.NO))
                    .filter(e -> sourceProductIds.contains(e.getProductId()))
                    .map(ServProduct::getName).collect(Collectors.toList());

            if (CollectionUtil.isNotNullOrEmpty(productName) && CollectionUtil.isNotNullOrEmpty(showProductName)) {
                throw new PlatException("该后台产品已关联前台产品：【" + Joiner.on("、").join(showProductName) + "】,请先取消关联后再操作！");
            }
        }
    }
}
